package com.zh.zhbootcommon.utils.io;

import cn.hutool.core.date.DateUtil;
import com.zh.zhbootcommon.config.minio.MinIoProperties;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.messages.Bucket;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 描述: MinIo 工具类
 * <p>
 * Java Client API参考文档：https://docs.min.io/cn/java-client-api-reference.html
 *
 * @author: yanglin
 * @Date: 2021-09-01-13:38
 * @Version: 1.0
 */
@Slf4j
@Component
public class MinIoUtils {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinIoProperties minIoProperties;

    /**
     * 检查存储桶是否存在
     *
     * @param bucketName 存储桶名称
     * @return
     */
    @SneakyThrows
    public boolean bucketExists(String bucketName) {
        boolean flag = false;
        flag = minioClient.bucketExists(bucketName);
        if (flag) {
            return true;
        }
        return false;
    }

    /**
     * 创建 bucket
     *
     * @param bucketName: 桶名
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public void createBucket(String bucketName) {
        boolean isExist = minioClient.bucketExists(bucketName);
        if (!isExist) {
            minioClient.makeBucket(bucketName);
        }
    }

    /**
     * 获取全部bucket
     *
     * @param :
     * @return: java.util.List<io.minio.messages.Bucket>
     */
    @SneakyThrows(Exception.class)
    public List<Bucket> getAllBuckets() {
        return minioClient.listBuckets();
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param filePath:   文件路径
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public void upload(String bucketName, String fileName, String filePath) {
        minioClient.putObject(bucketName, fileName, filePath, null);
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param stream:     文件流
     * @return: java.lang.String : 文件url地址
     */
    @SneakyThrows(Exception.class)
    public String upload(String bucketName, String fileName, InputStream stream) {
        minioClient.putObject(bucketName, fileName, stream, new PutObjectOptions(stream.available(), -1));
        return getFileUrl(bucketName, fileName);
    }

    /**
     * 文件上传
     *
     * @param bucketName: 桶名
     * @param file:       文件
     * @return: java.lang.String : 文件url地址
     */
    @SneakyThrows(Exception.class)
    public String upload(String bucketName, MultipartFile file) {
        final InputStream is = file.getInputStream();
        String date = DateUtil.format(new Date(), "yyyy-MM-dd");
        // 重命名
        String suffix = file.getOriginalFilename().split("\\.")[1];
        final String fileName = date + "/" +  UUID.randomUUID().toString() + "." + suffix;
        minioClient.putObject(bucketName, fileName, is, new PutObjectOptions(is.available(), -1));
        is.close();
        String url = "http://" + minIoProperties.getEndpoint() + ":" + minIoProperties.getPort() + "/" + minIoProperties.getBucketName() + "/" + fileName;
        url = getFileUrl(bucketName, fileName);
        return url;
    }

    /**
     * 删除文件
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public void deleteFile(String bucketName, String fileName) {
        minioClient.removeObject(bucketName, fileName);
    }

    /**
     * 下载文件
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @param response:
     * @return: void
     */
    @SneakyThrows(Exception.class)
    public void download(String bucketName, String fileName, HttpServletResponse response) {
        // 获取对象的元数据
        final ObjectStat stat = minioClient.statObject(bucketName, fileName);
        response.setContentType(stat.contentType());
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        String date = DateUtil.format(new Date(), "yyyy-MM-dd");
        // 重命名
        String suffix = fileName.split("\\.")[1];
        final String newFileName = UUID.randomUUID().toString() + "." + suffix;
        InputStream is = minioClient.getObject(bucketName, newFileName);
        IOUtils.copy(is, response.getOutputStream());
        is.close();
    }

    /**
     * 获取minio文件的下载地址
     *
     * @param bucketName: 桶名
     * @param fileName:   文件名
     * @return: java.lang.String
     */
    @SneakyThrows(Exception.class)
    public String getFileUrl(String bucketName, String fileName) {
        return minioClient.presignedGetObject(bucketName, fileName);
    }

    public MinIoProperties getMinIoProperties() {
        return minIoProperties;
    }

    public void setMinIoProperties(MinIoProperties minIoProperties) {
        this.minIoProperties = minIoProperties;
    }
}
